#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "envel.h"
#include "lab2.h"
#include "constantes.h"


void carregamsgs (FILE *idioma, char **msgs)
/* carrega em um vetor de strings*/
{
    char string[100], chr;
	int i=0, j=0;

    while (!feof(idioma)) //Enquanto não fim de arquivo
    {
          chr = getc(idioma);
          while (chr != EOF && chr != '\n')//condição de fim de mensagem
          {
                string[i] = chr;
                i++;
                chr = getc(idioma);
          }
          string[i] = '\0';//null-character é colocado no fim desta string
          msgs[j] = (char *)Malloc(strlen(string)+4);//aloca espaço para mensagem
          strcpy(msgs[j], string);//mensagem adicionada ao vetor de string
          j++;
          i = 0;
    }
}

int registrosValidos(FILE *f, char *msg[])
/*verifica todos registros do arq entrada*/
{
    int i = 0, nReg = 1, RegValido = true;//RegValido = flag que indica arq de registros valido ou não
    char c = getc(f);

    while(!feof(f))
    {
        for (i = 0; i < 6; i++)//verificação dos RA
        {
            if (!NUMERICO)
            {
                 printf("Reg n. %d: %s\n", nReg, msg[1]); //ra inconsistente
                 RegValido = false;

            }
            c = getc(f);
        }
        for (i = 0; i < 24; i++) //verificação dos nomes
        {
            c = getc(f);
            if (!ALFANUMERICO && c != ' ')
            {
                 printf("Reg n. %d: %s\n", nReg, msg[2]); //nome inconsistente
                 RegValido = false;

            }
        }
        for (i = 0; i < 15; i++)//verificação dos nomes das cidades
        {
            c = getc(f);
            if (!ALFANUMERICO && c != ' ')
            {
                 printf("Reg n. %d: %s\n", nReg, msg[3]); //cidade nao consistente
                 RegValido = false;

            }
        }
        for (i = 0; i < 8; i++)//verificação dos numeros de telefone
        {
            c = getc(f);
            if (!NUMERICO)
            {
                 printf("Reg n. %d: %s\n", nReg, msg[4]); //n tel inconsistente ou inexistente
                 RegValido = false;

            }
        }
        c = getc(f);
        for (i = 0; i < 8; i++)//verificação dos numeros de telefone alternativos
        {
            c = getc(f);
            if (!NUMERICO && c != ' ')
            {
                 printf("Reg n. %d: %s\n", nReg, msg[5]); //n tel alt inconsistente
                 RegValido = false;

            }
        }
        c = getc(f); c = getc(f);
        if (!SEXO)//verificação dos sexos
        {
            printf("Reg n. %d: %s\n", nReg, msg[6]); //sexo declarado inconsistente
            RegValido = false;
        }
        c = getc(f);
        for (i = 0; i < 2; i++) //verificação dos numeros de curso
        {
            c = getc(f);
            if (!NUMERICO)
            {
                 printf("Reg n. %d: %s\n", nReg, msg[7]); //n curso inconsistente
                 RegValido = false;

            }
        }
        c = getc(f);
        if (c != FIMREGISTRO)//verificação do caractere indicador de fim de registro
        {
            printf("Reg n. %d: %s\n", nReg, msg[8]); //separador de registros inconsistente
            RegValido = false;
        }
        nReg++;
        c = getc(f);
        c = getc(f);
    }
    if (!RegValido) return false;
    else return true;
}

int arqEntradaValido(char entrada[], char *msg[])
/*checa existencia do arq entrada e seus registros*/
{
    FILE *f;
    f = fopen(entrada, "r");
    /*verifica existencia do arq de entrada*/
    if(!arqExistente(f))
    {
        printf("%s\n", msg[0]); //arquivo inexistente
        return false;
    }
    else
    {
    	/*verifica validade dos registros*/
        if(!registrosValidos(f, msg)) return false;
    }
    fclose(f);
    return true;
}

void liberaMsgs(char *msg[]) //libera memoria dinamica das mensagens
{
    int i;

    for (i = 0; i < N_MSGS; i++) free(msg[i]);
}

void cardapio(char *msg[], char Entrada[0], char Saida[0]) //Funcao cardapio
{
	int opcao = 0;

	while(opcao != 10){

		printf("%s\n%s\n%s\n%s\n%s\n\n", msg[10], msg[10], msg[11], msg[10], msg[10]);
		printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", msg[12], msg[13], msg[14], msg[15], msg[16], msg[17], msg[18], msg[19], msg[20], msg[21]);


		//aqui comeca os switches para as opcoes
		scanf("%d", &opcao);

		switch (opcao){

			 case 1:
				 converteArquivo(Entrada, Saida);
				 break;
			 case 2:
				 listaArquivoFixo(msg, Entrada);
				 break;
			 case 3:
				listaArquivoVariavel(msg, Entrada, Saida);
				break;
			 case 4:
				 pesquisaRegistro(msg, Entrada, Saida);
				 break;
			 case 10:
				 break;
			 default:
				 printf("\n%s\n", msg[9]);
				 break;
		}

	}
}

void converteArquivo(char Entrada[0],char Saida[0])
/* Monta um vetor com os dados já na formatação em que será salva em um arquivo de saida */
{
	FILE *entrada, *saida;
	int contRegistro=1, contVetor=0;
	char *registros, aux;

	entrada = fopen(Entrada, "r");

	registros = (char*)malloc(sizeof(char)); /*Alocando memória inicial*/
	aux = getc(entrada);

	while (!feof(entrada)) /*Enquanto não fim de arquivo*/
	{
		if(contRegistro%TAMREGISTRO == INICIOCAMPO3 || contRegistro%TAMREGISTRO == INICIOCAMPO4)
		{
			registros = (char*)realloc(registros, contVetor+1);/* Realoco a memória, agora com o tamanho certo do vetor que contém os registros */
			registros[contVetor] = CARACTERSEPARADOR;
			contVetor++;
		}
		if(contRegistro%TAMREGISTRO == FIMCAMPO1 || contRegistro%TAMREGISTRO == FIMCAMPO4 || contRegistro%TAMREGISTRO == FIMCAMPO5 || contRegistro%TAMREGISTRO == FIMCAMPO6)
		{
			registros = (char*)realloc(registros, contVetor+1);/* Realoco a memória, agora com o tamanho certo do vetor que contém os registros */
			registros[contVetor] = CARACTERSEPARADOR;
			contRegistro++;
			contVetor++;
			aux = getc(entrada);
		}
		if(aux == ' ')
		{
			aux = getc(entrada);
			if(aux == ' ')
			{
				do
				{
					aux = getc(entrada);
					contRegistro++;
				} while(aux == ' ');
				registros = (char*)realloc(registros, contVetor+1);/* Realoco a memória, agora com o tamanho certo do vetor que contém os registros */
				registros[contVetor] = CARACTERSEPARADOR;
				contVetor++;
				contRegistro++;
			} else {
				contRegistro++;
				registros = (char*)realloc(registros, contVetor+1);/* Realoco a memória, agora com o tamanho certo do vetor que contém os registros */
				if(contRegistro%TAMREGISTRO == INICIOCAMPO3 || contRegistro%TAMREGISTRO == INICIOCAMPO4)
				{
					registros[contVetor] = CARACTERSEPARADOR;
				} else {
					registros[contVetor] = ' ';
				}
				contVetor++;
			}

		}
		registros = (char*)realloc(registros, contVetor+1);/* Realoco a memória, agora com o tamanho certo do vetor que contém os registros */
		registros[contVetor] = aux;
		contRegistro++;
		contVetor++;
		aux = getc(entrada);/* Caminho no arquivo de entrada */




	}
	saida = fopen(Saida, "w");
	fwrite(registros, strlen(registros), 1, saida);/*Coloco no arquivo de saida o vetor criado*/

	free(registros);

	fclose(entrada);
	fclose(saida);
}

void listaArquivoFixo(char *msgs[], char Entrada[])
/* Monta um vetor com os dados já na formatação em que será salva em um arquivo de saida */
{
	FILE *entrada, *saida;
	int i, i2, i3, contVetor = 0, contCampo = 0, contRegistro = 1;
	char *camposRegistros[NUMEROCAMPOS], registros[TAMMAXIMOINFORMACOES], campo[TAMMAXCAMPO], aux;

	entrada = fopen(Entrada, "r");
	saida = fopen("Informacoes.txt", "a+");

	for(i=0; i<NUMEROREGISTROS; i++)
	{
		aux = getc(entrada);
		while(aux != '\n')
		{
			if(contRegistro == FIMCAMPO1 || contRegistro == INICIOCAMPO3 || contRegistro == INICIOCAMPO4 || contRegistro == FIMCAMPO4 || contRegistro == FIMCAMPO5 || contRegistro == FIMCAMPO6 || contRegistro == CAMPOSEPARADOR)
			{
				campo[contVetor] = '\0';
				camposRegistros[contCampo] = (char*)Malloc(strlen(campo)+2);
				strcpy(camposRegistros[contCampo], campo);
				strcat(camposRegistros[contCampo], "\n");
				if(contRegistro == FIMCAMPO1 || contRegistro == FIMCAMPO4 || contRegistro == FIMCAMPO5 || contRegistro == FIMCAMPO6)
				{
					contRegistro++;
					aux = getc(entrada);
				}
				contCampo++;
				contVetor = 0;
			}
			campo[contVetor] = aux;
			contVetor++;
			contRegistro++;
			aux = getc(entrada);
		}
		contVetor = 0;
		contCampo = 0;
		contRegistro = 1;

		strcpy(registros, msgs[22]);
		strcat(registros, "\n\n");

		for(i2=0; i2< NUMEROCAMPOS; i2++)
		{
			strcat(registros, msgs[i2+23]);
			strcat(registros, camposRegistros[i2]);

		}
		strcat(registros, "\n\n");

		fwrite(registros, strlen(registros), 1, saida);

		for(i3=0; i3 < NUMEROCAMPOS; i3++)
		{
			free(camposRegistros[i3]);
		}
	}

	fclose(entrada);
	fclose(saida);

}

void listaArquivoVariavel(char *msg[],char Entrada[0],char Saida[0])
/* Leio um arquivo de saida no formato variável
 * e de acordo com o mesmo é salvo em outro arquivos as
 * informações do arquivo e do registro */
{

	converteArquivo(Entrada, Saida);/* Criação do arquivo de saida*/

	char aux;

	int posicaoAtual=0, posicaoInicial=0, tam=0, i=23, numreg=0;

	FILE *arqvar, *arqsaida;

	arqvar = fopen(Saida, "r");
    if(!arqExistente(arqvar))
    {
        printf("%s\n", msg[0]); //arquivo inexistente
        return;
    }

	arqsaida = fopen("ListaRegistrosArqVar.txt", "w+");

	posicaoAtual = ftell(arqvar); //posição atual do arquivo

	// calculo do tamanho do arquivo
	fseek(arqvar, 0, SEEK_END);
	tam = ftell(arqvar);

    fseek(arqvar, 0, SEEK_SET);//Retornando a posição inicial do arquivo


	fprintf (arqsaida, "%s %d bytes\n",msg[30],tam); /*Imprime no buffer o que será salvo no arquivo(Físico)*/
	aux = getc(arqvar);

	while (!feof(arqvar)){ //Enquanto não fim do arquivo

		numreg++; //Contador do número de registros

		fprintf (arqsaida, "%s\n %s %d\n",msg[10], msg[22], numreg);/*Imprime no buffer o que será salvo no arquivo(Físico)*/

		i=23;

		while(aux!= FIMREGISTRO){

			posicaoInicial = ftell(arqvar);

			fprintf (arqsaida, "\n %s",msg[i]);/*Imprime no buffer o que será salvo no arquivo(Físico)*/

			i++;

			while(aux != CARACTERSEPARADOR && aux != FIMREGISTRO){
				fprintf (arqsaida, "%c",aux);/*Imprime no buffer o que será salvo no arquivo(Físico)*/
				aux = getc(arqvar);
			}

			posicaoAtual = ftell(arqvar);

			/*Imprime no buffer o que será salvo no arquivo(Físico)*/
			fprintf (arqsaida, "\n %s %d",msg[31], posicaoAtual-posicaoInicial);
			fprintf (arqsaida, "\n %s %d\n",msg[32], posicaoInicial);

			if (aux != FIMREGISTRO){
				aux = getc(arqvar);
			}

		}
		aux = getc(arqvar);

		if(aux == '\n'){ //Caminho no arquivo de entrada
			/*Imprime no buffer o que será salvo no arquivo(Físico)*/
			fprintf (arqsaida, "%c",aux);
			aux = getc(arqvar);
		}


	}

	fclose(arqvar);
	fclose(arqsaida);
}

void pesquisaRegistro(char *msg[], char Entrada[0], char Saida[0])
{
	FILE *arquivoVariavel;
	int i, i2, numeroRegistro=0, posicaoInicialCampo, posicaoInicialRegistro, posicaoAtual;
	char aux, chavePrimaria[7], RA[7];

	converteArquivo(Entrada, Saida);

	scanf("%s", chavePrimaria);

	arquivoVariavel = fopen(Saida, "r");

	if(!arqExistente(arquivoVariavel))
	{
		printf("%s\n", msg[0]); //arquivo inexistente
	    return;
	}

	aux = getc(arquivoVariavel);
	while (!feof(arquivoVariavel))
	{
		i=0;
		numeroRegistro++;

		posicaoInicialCampo = ftell(arquivoVariavel);
		posicaoInicialRegistro = posicaoInicialCampo;

		do
		{
			RA[i] = aux;
			i++;
			aux = getc(arquivoVariavel);
		} while(aux != CARACTERSEPARADOR);
		RA[i] = '\0';

		if(!strcmp(chavePrimaria, RA))
		{
			i2 = 23;
			posicaoAtual = ftell(arquivoVariavel);

			printf("%s\n %s %d\n",msg[10], msg[22], numeroRegistro);
			printf ("\n %s %s",msg[i2], RA);
			printf ("\n %s %d",msg[31], posicaoAtual-posicaoInicialCampo);
			printf ("\n %s %d\n",msg[32], posicaoInicialCampo);

			i2++;
			aux = getc(arquivoVariavel);

			while(aux != FIMREGISTRO)
			{
				posicaoInicialCampo = ftell(arquivoVariavel);

				printf ("\n %s",msg[i2]);
				i2++;

				while(aux != CARACTERSEPARADOR && aux != FIMREGISTRO)
				{
					printf ("%c",aux);
					aux = getc(arquivoVariavel);
				}

				posicaoAtual = ftell(arquivoVariavel);

				printf ("\n %s %d",msg[31], posicaoAtual-posicaoInicialCampo);
				printf ("\n %s %d\n",msg[32], posicaoInicialCampo);

				if (aux != FIMREGISTRO){
					aux = getc(arquivoVariavel);
				}

			}
			printf("\n %s %d bytes", msg[33], posicaoAtual-posicaoInicialRegistro);
			return;
		} else {

			do
			{
				aux = getc(arquivoVariavel);
			} while(aux != '\n');
			aux = getc(arquivoVariavel);
		}

	}
	printf("\n%s\n", msg[34]);

	fclose(arquivoVariavel);
}

int main(int argc, char *argv[])
{
    FILE *f, *idioma;
    char *msg[N_MSGS], c;
    /*verifica se numero de argumentos passados na linha de comando é valido */
    if (argc < 3)
    {
        printf("\nArgumentos insuficientes para execucao do programa!\nInsufficient arguments for execution of the program!");
        exit(EXIT_FAILURE);
    }

    printf("\nPor favor, selecione o idioma desejado\nPlease select one language to proceed\n");
    printf("\n\nPortugues (p)\nEnglish (i)\n");

    scanf("%c", &c);
    /* opcao de idioma escolhida pelo usuario */

    if(c == 'i'){
        idioma = fopen("ing.txt", "r");
    } else {
        idioma = fopen("por.txt", "r");
    }

    /*caso o arquivo de mensagens esteja ausente*/
    if (!arqExistente(idioma))
    {
        printf("\nArquivo de mensagens inexistente!\nFile of messages missing!\n");
        exit(EXIT_FAILURE);
    }

    /*chama função que carrega mensagens do programa em um vetor de strings*/
    carregamsgs(idioma, &msg[0]);

    /*fecha arquivo de mensagens*/
    fclose(idioma);

    /*verifica validade do arquivo de registros*/
    if(!arqEntradaValido(argv[1], msg)) exit(EXIT_FAILURE);

    /*Aqui chama a funcao para mostrar cardapio*/
    cardapio(msg, argv[1], argv[2]);

    /* libera vetor de strings com mensagens do programa */
    liberaMsgs(msg);

    return 0;
}

